home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’92 / Trash Selector / Trash Selector Source / Main.c next >
Encoding:
C/C++ Source or Header  |  1992-06-19  |  22.3 KB  |  1,004 lines  |  [TEXT/KAHL]

  1. /*
  2.  
  3.     TRASH SELECTOR
  4.     by Carl W. Haynes III
  5.     Haynes Consulting Services
  6.     PO Box 2715
  7.     W. Lafayette, IN 47906
  8.     
  9.     haynes@mace.cc.purdue.edu
  10.     CWH3@aol.com
  11.     
  12.     Sorry about the no comments/docs, I'm out of time (almost midnight)
  13.     
  14.     Hold down the option key to override my patch when you select
  15.     empty trash from the finders menu
  16. */
  17.  
  18.  
  19. #include <SetupA4.h>
  20.  
  21. #include "Main.h"
  22.  
  23. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  24.  
  25. void main()
  26. {
  27. Handle    self_handle;                    // a handle to our own code resource */
  28. Handle    show_init;
  29. Boolean ThereWasAnError;
  30. int        myErr;
  31. Boolean    systemSevenOrLater;
  32.  
  33.     CODE_SETUP();                        // push registers to stack, setup A4 */
  34.     
  35.     asm
  36.         {
  37.             _RecoverHandle                    // A0 already set up
  38.             move.l a0, self_handle            //
  39.         }
  40.         
  41.     HLock(self_handle);
  42.  
  43.     DetachResource(self_handle);        // so we'll stay after file closed */
  44.         
  45.     init_mac();                            // initialize toolbox 
  46.     
  47.     
  48.     if(systemSevenOrLater = CheckForSystem7())
  49.     {
  50.         if ((show_init = Get1Resource( 'Code', -4048 )) != 0L)
  51.         {
  52.             HLock( show_init );
  53.             CallPascal( icon_family_ID, *show_init );
  54.             HUnlock( show_init );
  55.             HPurge(show_init);
  56.         }
  57.         
  58.         load_it();                            // steal the trap 
  59.     }
  60.     else
  61.     {
  62.         if ((show_init = Get1Resource( 'Code', -4048 )) != 0L)
  63.         {
  64.             HLock( show_init );
  65.             CallPascal( DontLoadIcon, *show_init );
  66.             HUnlock( show_init );
  67.             HPurge(show_init);
  68.         }
  69.     }
  70.     
  71.     CODE_CLEANUP();                        // restore the registers 
  72. }
  73.  
  74.  
  75.  
  76.  
  77. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  78.  
  79. init_mac()
  80. {
  81.     InitGraf(&our_qd.thePort);
  82. }
  83.  
  84. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  85.  
  86. load_it()
  87. {
  88.     RememberA4();        /* put a4 contents into CODE segment storage */
  89.  
  90.     itemList = Get1Resource('DITL', 128);
  91.     DetachResource(itemList);
  92.     HNoPurge(itemList);
  93.  
  94.     gMyLDEF = Get1Resource('LDEF', 130);
  95.     DetachResource(gMyLDEF);
  96.     HNoPurge(gMyLDEF);
  97.  
  98.     old_MenuSelect = NGetTrapAddress(MenuSelect_TRAP, ToolTrap);
  99.     NSetTrapAddress((long)our_MenuSelect, MenuSelect_TRAP, ToolTrap);
  100.  
  101.     gOldJGNE = (long)JGNEFilter;
  102.     JGNEFilter = (ProcPtr)myJGNE;
  103. }
  104.  
  105. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  106.  
  107. pascal long our_MenuSelect(Point where)
  108. {
  109. long    returnValue;
  110.  
  111.     asm { 
  112.             movem.l    a1-a5/D0-D7, -(SP)    ; Save registers
  113.     }
  114.         
  115.     SetUpA4();                            // So we can find globals 
  116.  
  117.     gOurMenuWasSelected = FALSE;
  118.     
  119.     returnValue = CallPascalL(where, old_MenuSelect);
  120.                         
  121.        if ( (HiWord(returnValue) == 261) && (LoWord(returnValue) == 2) ) 
  122.        {
  123.           if (! KeyIsDown(kScanCodeOption))
  124.            {
  125.             PtoCstr(&CurApName);
  126.                if (strstr(&CurApName, "Finder")) 
  127.                {
  128.                    gOurMenuWasSelected = TRUE;
  129.                 returnValue = 0L;
  130.                }
  131.                CtoPstr(&CurApName);
  132.            }
  133.        }
  134.  
  135.       asm    {
  136.                 movea.l    (A7)+,A4            // RestoreA4();
  137.                 movem.l    (SP)+, a1-a5/D0-D7  // Restore registers
  138.     }
  139.  
  140.     return(returnValue);
  141. }
  142.  
  143. void DoTrashDialog(void)
  144. {
  145. Rect        wRect;
  146. Boolean        dlgDone;
  147. DialogPtr    theDialog;
  148. Handle        copyOfItemList;
  149. Ptr            dStorage;
  150. GrafPtr        savedPort;
  151. Rect        theRect;
  152. Handle        theItem;
  153. short        theType;
  154. PenState    savedPenState;
  155. Rect        dataBounds;
  156. Point        cellSize = {0, 0};
  157. short        listWidth, listHeight;
  158. short        numOfCellsThatFit;
  159. Handle        savedLDEF;
  160. Boolean        trashSelected = FALSE;
  161.  
  162.     GetPort(&savedPort);
  163.     GetPenState(&savedPenState);
  164.     
  165.     copyOfItemList = itemList;
  166.     HandToHand(©OfItemList);
  167.     
  168.     SetRect(&wRect, 70, 48, 470, 323);
  169.     dStorage = NewPtrSysClear(sizeof(DialogRecord));
  170.     
  171.     theDialog = NewDialog(    dStorage,                     //    storage
  172.                             &wRect,                     //    wRect
  173.                             "\pTrash Selector",         //    title
  174.                             FALSE,                         //    visible
  175.                             noGrowDocProc,                 //    wDefProcID
  176.                             (DialogPtr)-1L,             //    behind
  177.                             FALSE,                         //    goAwayFlag 
  178.                             0L,                         //    refCon
  179.                             copyOfItemList);             //    itemList
  180.     SetPort(theDialog);
  181.     
  182.     GetDItem(theDialog, kListUI, &theType, &theItem, &theRect);
  183.                 
  184.     SetRect(&dataBounds, 0, 0, 1, 0);
  185.     gTheList = LNew(    &theRect,
  186.                         &dataBounds,
  187.                         cellSize,
  188.                         0,
  189.                         theDialog, 
  190.                         TRUE,
  191.                         FALSE,
  192.                         FALSE,
  193.                         TRUE);
  194.     if (gTheList == nil)
  195.     {
  196.         DebugStr("\pgTheList == nil");
  197.         return;
  198.     }
  199.     SetWRefCon(theDialog, (long)gTheList);
  200.  
  201.     HLock(gMyLDEF);
  202.     savedLDEF = (**gTheList).listDefProc;
  203.     (**gTheList).listDefProc = gMyLDEF;
  204.     (**gTheList).selFlags = lExtendDrag;
  205.     HLock(gTheList);
  206.  
  207.     listWidth = (**gTheList).rView.right - (**gTheList).rView.left;
  208.     numOfCellsThatFit = ((**gTheList).rView.bottom - (**gTheList).rView.top) / (**gTheList).cellSize.v;
  209.     listHeight = numOfCellsThatFit * (**gTheList).cellSize.v;    
  210.     LSize(listWidth, listHeight, gTheList);
  211.  
  212.     gBaseTrashItem = (TrashItemsHdl)NewHandleSysClear(sizeof(TrashItemsRec));
  213.  
  214.     BuildTrashList(gTheList);
  215.     DisplayInitialList(gTheList);
  216.     HUnlock(gTheList);
  217.     
  218.     ShowWindow(theDialog);
  219.     
  220.     dlgDone = FALSE;
  221.     while (dlgDone == FALSE)
  222.     {
  223.     short itemHit;
  224.     
  225.         ModalDialog((ProcPtr)TrashFilter, &itemHit);
  226.         
  227.         switch (itemHit)
  228.         {
  229.         Str255    tempString;
  230.         long    totalSelected;
  231.         long    endTime;
  232.         
  233.             case kDoUpdate:
  234.             
  235.                 BeginUpdate(theDialog);
  236.                 
  237.                 PenNormal();
  238.                 
  239.                 DrawDialog(theDialog);
  240.                 
  241.                 PenSize(1, 1);
  242.                 FrameRect(&theDialog->portRect);
  243.                 PenNormal();
  244.                 
  245.                 GetDItem(theDialog, kTrashButton, &theType, &theItem, &theRect);
  246.                 InsetRect(&theRect, -4, -4);
  247.                 PenSize(3, 3);
  248.                 FrameRoundRect(&theRect, 16, 16);
  249.                 PenNormal();
  250.  
  251.                 GetDItem(theDialog, kTitleBoxUI, &theType, &theItem, &theRect);
  252.                 InvertRect(&theRect);
  253.                 
  254.                 theRect = (**gTheList).rView;
  255.                 InsetRect(&theRect, -1, -1);
  256.                 FrameRect(&theRect);
  257.                 
  258.                 HLock(gTheList);
  259.                 LUpdate(theDialog->visRgn, gTheList);
  260.                 HUnlock(gTheList);
  261.  
  262.                 TextFont(applFont);
  263.                 TextSize(9);
  264.                 
  265.                 GetDItem(theDialog, kTotalSelectedUI, &theType, &theItem, &theRect);
  266.                 strcpy((Ptr)&tempString, "Total Selected: ");
  267.                 TextBox(&tempString, strlen((Ptr)&tempString), &theRect, teJustLeft);
  268.                 
  269.                 totalSelected = GetTotalSelected(gTheList);
  270.                 GetDItem(theDialog, kTotalUnselectedUI, &theType, &theItem, &theRect);
  271.                 NumToString(totalSelected, &tempString);
  272.                 PtoCstr(&tempString);
  273.                 strcat((Ptr)&tempString, "K");
  274.                 TextBox(&tempString, strlen((Ptr)&tempString), &theRect, teJustLeft);
  275.  
  276.                 TextFont(systemFont);
  277.                 TextSize(12);
  278.                 PenNormal();
  279.                 EndUpdate(theDialog);
  280.                 break;
  281.             case kSelectAllButton:
  282.                 SelectAll(gTheList);
  283.                 GetDItem(theDialog, kTotalUnselectedUI, &theType, &theItem, &theRect);
  284.                 InvalRect(&theRect);
  285.                 break;
  286.             case kDeselectAllButton:
  287.                 DeselectAll(gTheList);
  288.                 GetDItem(theDialog, kTotalUnselectedUI, &theType, &theItem, &theRect);
  289.                 InvalRect(&theRect);
  290.                 break;
  291.             case kTrashButton:
  292.                 trashSelected = TRUE;
  293.                 dlgDone = TRUE;
  294.                 break;
  295.             case kCancelButton:
  296.                 dlgDone = TRUE;
  297.                 break;
  298.             case kKeyOK:
  299.                 GetDItem(theDialog, kTrashButton, &theType, &theItem, &theRect);
  300.                 HiliteControl((ControlHandle)theItem, 1);
  301.                 Delay(10, &endTime);
  302.                 HiliteControl((ControlHandle)theItem, 0);
  303.                 trashSelected = TRUE;
  304.                 dlgDone = TRUE;
  305.                 break;
  306.             case kKeyCancel:
  307.                 GetDItem(theDialog, kCancelButton, &theType, &theItem, &theRect);
  308.                 HiliteControl((ControlHandle)theItem, 1);
  309.                 Delay(10, &endTime);
  310.                 HiliteControl((ControlHandle)theItem, 0);
  311.                 dlgDone = TRUE;
  312.                 break;
  313.             case kDoNothing:
  314.                 break;
  315.             default:
  316.                 break;
  317.         }
  318.     }
  319.  
  320.     if (trashSelected)
  321.     {
  322.         DeleteSelected(gTheList);
  323.     }
  324.  
  325.     while (gBaseTrashItem != nil)
  326.     {
  327.     TrashItemsHdl tempTrashItems;
  328.  
  329.         tempTrashItems = (**gBaseTrashItem).next;
  330.         DisposHandle(gBaseTrashItem);
  331.         gBaseTrashItem = tempTrashItems;        
  332.     }
  333.     gBaseTrashItem = nil;
  334.     
  335.     (**gTheList).listDefProc = savedLDEF;
  336.     HUnlock(gMyLDEF);
  337.  
  338.     LDispose(gTheList);
  339.     gTheList = nil;
  340.  
  341.     HideWindow(theDialog);
  342.     CloseDialog(theDialog);
  343.     
  344.     DisposHandle(copyOfItemList);
  345.     DisposePtr(dStorage);
  346.     
  347.     SetPort(&savedPort);
  348.     SetPenState(&savedPenState);
  349. }
  350.  
  351. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  352.  
  353. pascal Boolean TrashFilter(DialogPtr theDialog, EventRecord *dlgEvent, short *itemHit)
  354. {
  355. Rect    theRect;
  356. Handle    theItem;
  357. short    theType;
  358.  
  359.     switch ((*dlgEvent).what)
  360.     {
  361.         case updateEvt:
  362.         {
  363.             *itemHit = kDoUpdate;
  364.             return(TRUE);
  365.         }
  366.         case mouseDown:
  367.         {
  368.         Point localPt;
  369.         
  370.             localPt = dlgEvent->where;
  371.             GlobalToLocal(&localPt);
  372.             
  373.             GetDItem(theDialog, kListUI, &theType, &theItem, &theRect);
  374.             theRect.right += 16;
  375.                         
  376.             if (PtInRect(localPt, &theRect))
  377.             {
  378.             Cell    lastCellClicked;
  379.             
  380.                 if (LClick(localPt, dlgEvent->modifiers, gTheList))
  381.                 {
  382.                 ListEntryRec    listEntry;
  383.                 short            dataLen;
  384.                 Cell            theCell = {0,0};
  385.                         
  386.                     SetPt(&theCell, 0, 0);
  387.                     if (LGetSelect(TRUE, &theCell, gTheList)) 
  388.                     {
  389.                     Str255 tempString;
  390.                     
  391.                         dataLen = sizeof(ListEntryRec);
  392.                         LGetCell(&listEntry, &dataLen, theCell, gTheList);
  393.                         
  394.                         switch(listEntry.type)
  395.                         {
  396.                             case kOpenFolderType:
  397.                             {
  398.                                 listEntry.type = kClosedFolderType;
  399.                                 dataLen = sizeof(ListEntryRec);
  400.                                 LSetCell(&listEntry, dataLen, theCell, gTheList);
  401.                                 LDraw(theCell, gTheList);
  402.                                 break;
  403.                             }
  404.                             case kClosedFolderType:
  405.                             {
  406.                                 listEntry.type = kOpenFolderType;
  407.                                 LSetCell(&listEntry, dataLen, theCell, gTheList);
  408.                                 LDraw(theCell, gTheList);
  409.                                 break;
  410.                             }
  411.                             case kFileType:
  412.                             {
  413.                                 break;
  414.                             }
  415.                             case kApplicationType:
  416.                             {
  417.                                 break;
  418.                             }
  419.                             default:
  420.                                 break;
  421.                         }
  422.                     }
  423.                 }                
  424.                 if (myLClikLoop()){}
  425.                 GetDItem(theDialog, kTotalUnselectedUI, &theType, &theItem, &theRect);
  426.                 InvalRect(&theRect);
  427.             }
  428.             else
  429.             {
  430.             WindowPtr    theWindow;
  431.             Point        tempPt;
  432.             
  433.                 tempPt = dlgEvent->where;
  434.                 
  435.                 if (FindWindow(tempPt, &theWindow) == inDrag)
  436.                 {
  437.                 Rect limitRect;
  438.                 
  439.                     SetRect(&limitRect, -32000, -32000, 32000, 32000);
  440.                     DragWindow(theDialog, tempPt, &limitRect);
  441.                     *itemHit = kDoNothing;
  442.                     return(TRUE);
  443.                 }
  444.             }
  445.             
  446.             return(FALSE);
  447.         }
  448.         case keyDown:
  449.         {
  450.         char    theChar;
  451.         Boolean CmdKeyDown;
  452.  
  453.             theChar         = (*dlgEvent).message & charCodeMask;
  454.             CmdKeyDown         = (((*dlgEvent).modifiers & cmdKey) != 0);
  455.     
  456.             if (CmdKeyDown)
  457.             {
  458.                 switch (theChar)
  459.                 {
  460.                     case kPeriodKey:
  461.                     {
  462.                         *itemHit = kKeyCancel;
  463.                         return(TRUE);
  464.                         break;
  465.                     }
  466.                     default:
  467.                     {
  468.                         break;
  469.                     }
  470.                 }
  471.             }
  472.             else
  473.             {
  474.                 switch (theChar)
  475.                 {
  476.                     case kReturnKey:
  477.                     case kEnterKey:
  478.                     {
  479.                         *itemHit = kKeyOK;
  480.                         return(TRUE);
  481.                         break;
  482.                     }
  483.                     case kESCKey:
  484.                     {
  485.                         *itemHit = kKeyCancel;
  486.                         return(TRUE);
  487.                         break;
  488.                     }
  489.                     default:
  490.                         break;
  491.                 }
  492.             }
  493.             
  494.             return(FALSE);
  495.             break;
  496.         }
  497.         default:
  498.         {
  499.             InitCursor();
  500.             return(FALSE);
  501.         }
  502.     }
  503. }
  504.  
  505. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  506. void PositionDialog(DialogPtr theDialog)
  507. {
  508. Rect     tempRect;
  509. Rect    screenRect;
  510. Rect    dialogRect;
  511. short    dialogHeight;
  512. short    dialogWidth;
  513. short    screenHeight;
  514. short    screenWidth;
  515.  
  516.     dialogRect = theDialog->portRect;
  517.     screenRect = screenBits.bounds;
  518.     screenRect.top += GetMBarHeight();
  519.     
  520.     dialogHeight = dialogRect.bottom - dialogRect.top;
  521.     dialogWidth = dialogRect.right - dialogRect.left;
  522.     
  523.     screenHeight = screenRect.bottom - screenRect.top;
  524.     screenWidth = screenRect.right - screenRect.left;
  525.  
  526.     tempRect.left = (screenRect.left + (screenWidth / 2)) - (dialogWidth / 2);
  527.     tempRect.top = (screenRect.top + (screenHeight / 3)) - (dialogHeight / 3);
  528.         
  529.     MoveWindow(theDialog, tempRect.left, tempRect.top, FALSE);
  530. }
  531.  
  532. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  533.  
  534. void BuildTrashList(ListHandle gTheList)
  535. {
  536. HFileInfo    myCPB;
  537. short        trashVRefNum;
  538. long        trashDirID;
  539. OSErr        myErr;
  540. OSErr        getVInfoErr;
  541. Ptr            namePtr;
  542. StringPtr    PBGetVInfoNamePtr;
  543. short        drvNum = 0;
  544. Str255        volName;
  545. short        vRefNum;
  546. long        freeBytes;
  547. Str255        errorStr;
  548. VolumeParam    pb;
  549.  
  550.     pb.ioCompletion = nil;
  551.     pb.ioVolIndex = 1;
  552.     PBGetVInfoNamePtr = (StringPtr)NewPtrSysClear(256);
  553.     pb.ioNamePtr = PBGetVInfoNamePtr;
  554.     pb.ioVRefNum = 0;
  555.  
  556.     while ( (getVInfoErr = PBGetVInfo(&pb, false)) != nsvErr)
  557.     {
  558.     ListEntryRec    theListEntry;
  559.     TrashItemsHdl    tempTrashItem;
  560.             
  561.         BlockMove(pb.ioNamePtr, &theListEntry.name, pb.ioNamePtr[0] + 1);                
  562.         theListEntry.vRefNum = pb.ioVRefNum;
  563.         theListEntry.parID = 0;
  564.         theListEntry.depth = 0;
  565.         theListEntry.type = kDiskType;
  566.         theListEntry.fileSize = 0L;
  567.  
  568.         tempTrashItem = gBaseTrashItem;
  569.         while ((**tempTrashItem).next != nil)
  570.         {
  571.             tempTrashItem = (**tempTrashItem).next;
  572.         }
  573.         HLock(tempTrashItem);
  574.         (**tempTrashItem).next = (TrashItemsHdl)NewHandleSysClear(sizeof(TrashItemsRec));
  575.          HUnlock(tempTrashItem);
  576.  
  577.         tempTrashItem = (**tempTrashItem).next;
  578.         HLock(tempTrashItem);
  579.         BlockMove(&theListEntry, &(**tempTrashItem).listEntry, sizeof(ListEntryRec));
  580.          HUnlock(tempTrashItem);
  581.  
  582.         myErr = FindFolder(    pb.ioVRefNum, 
  583.                             kTrashFolderType, 
  584.                             FALSE, 
  585.                             &trashVRefNum, 
  586.                             &trashDirID);
  587.  
  588.         gDepth = 1;
  589.     
  590.         namePtr = NewPtrSysClear(256);
  591.         gMyCPB.hFileInfo.ioNamePtr = (StringPtr)namePtr;
  592.         gMyCPB.hFileInfo.ioVRefNum = trashVRefNum;
  593.         gCurrentVRefNum = trashVRefNum;
  594.         EnumerateCatalog(trashDirID, gTheList);
  595.     
  596.         DisposPtr(namePtr);
  597.         
  598.         pb.ioVolIndex++;
  599.         pb.ioVRefNum = 0;
  600.     }
  601.  
  602.         DisposPtr(PBGetVInfoNamePtr);
  603.     
  604. }
  605.  
  606. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  607.  
  608.  
  609. void EnumerateCatalog (long int dirIDToSearch, ListHandle gTheList)
  610. short    int    index=1;
  611. OSErr    myErr = noErr;
  612.  
  613.     do
  614.     {
  615.         gMyCPB.hFileInfo.ioFDirIndex = index;
  616.         gMyCPB.hFileInfo.ioDirID = dirIDToSearch;    /* we need to do this every time    */
  617.                                                     /* through, since GetCatInfo        */
  618.                                                     /* returns ioFlNum in this field */
  619.         gMyCPB.hFileInfo.filler2 = 0;    /* Clear the ioACUser byte if search is         */
  620.                                         /* interested in it. Nonserver volumes won't  */
  621.                                         /* clear it for you and the value returned is */
  622.                                         /* meaningless. */
  623.         myErr= PBGetCatInfo(&gMyCPB,false);
  624.         if (myErr == noErr) 
  625.         {
  626.             if ((gMyCPB.hFileInfo.ioFlAttrib & ioDirMask) != 0)
  627.             {    
  628.             ListEntryRec    theListEntry;
  629.             TrashItemsHdl    tempTrashItem;
  630.             DirInfo            DirInfo;
  631.             
  632.                 BlockMove(gMyCPB.dirInfo.ioNamePtr, &theListEntry.name, gMyCPB.dirInfo.ioNamePtr[0] + 1);                
  633.                 theListEntry.vRefNum = gMyCPB.dirInfo.ioVRefNum;
  634.                 theListEntry.parID = gMyCPB.dirInfo.ioDrParID;
  635.                 theListEntry.depth = gDepth;
  636.                 theListEntry.type = kOpenFolderType;
  637.                 theListEntry.fileSize = 0L;
  638.  
  639.                 tempTrashItem = gBaseTrashItem;
  640.                 while ((**tempTrashItem).next != nil)
  641.                 {
  642.                     tempTrashItem = (**tempTrashItem).next;
  643.                 }
  644.                 HLock(tempTrashItem);
  645.                 (**tempTrashItem).next = (TrashItemsHdl)NewHandleSysClear(sizeof(TrashItemsRec));
  646.                 HUnlock(tempTrashItem);
  647.                 
  648.                 tempTrashItem = (**tempTrashItem).next;
  649.                 HLock(tempTrashItem);
  650.                 BlockMove(&theListEntry, &(**tempTrashItem).listEntry, sizeof(ListEntryRec));
  651.                 HUnlock(tempTrashItem);
  652.                 
  653.                 gDepth++;
  654.                 EnumerateCatalog(gMyCPB.hFileInfo.ioDirID, gTheList); /* recurse */
  655.                 gDepth--;
  656.  
  657.                 myErr = noErr; /* clear error return on way back */
  658.             }
  659.             else 
  660.             {
  661.             ListEntryRec    theListEntry;
  662.             TrashItemsHdl    tempTrashItem;
  663.             HFileInfo        tempCPB;
  664.                 
  665.                 BlockMove(gMyCPB.hFileInfo.ioNamePtr, &theListEntry.name, gMyCPB.hFileInfo.ioNamePtr[0] + 1);                
  666.                 theListEntry.vRefNum = gMyCPB.hFileInfo.ioVRefNum;
  667.                 theListEntry.parID = gMyCPB.hFileInfo.ioFlParID;
  668.                 theListEntry.depth = gDepth;
  669.                 if (gMyCPB.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
  670.                     theListEntry.type = kApplicationType;
  671.                 else
  672.                     theListEntry.type = kFileType;
  673.                 theListEntry.fileSize = ((gMyCPB.hFileInfo.ioFlLgLen + gMyCPB.hFileInfo.ioFlRLgLen) / 1024) + 1;
  674.  
  675.                 tempTrashItem = gBaseTrashItem;
  676.                 while ((**tempTrashItem).next != nil)
  677.                 {
  678.                     tempTrashItem = (**tempTrashItem).next;
  679.                 }
  680.                 HLock(tempTrashItem);
  681.                 (**tempTrashItem).next = (TrashItemsHdl)NewHandleSysClear(sizeof(TrashItemsRec));
  682.                 HUnlock(tempTrashItem);
  683.  
  684.                 tempTrashItem = (**tempTrashItem).next;
  685.                 HLock(tempTrashItem);
  686.                 BlockMove(&theListEntry, &(**tempTrashItem).listEntry, sizeof(ListEntryRec));
  687.                 HUnlock(tempTrashItem);
  688.             }
  689.         }
  690.         ++index;
  691.         
  692.     } while (myErr == noErr);
  693. }
  694.  
  695. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  696.  
  697. void DisplayInitialList(ListHandle gTheList)
  698. {
  699. TrashItemsHdl    tempTrashItem;
  700. short                newRow;
  701. Cell                theCell;
  702.  
  703.     LDelRow(0, 0, gTheList);
  704.  
  705.     tempTrashItem = (**gBaseTrashItem).next;
  706.     while (tempTrashItem != nil)
  707.     {
  708.         HLock(tempTrashItem);
  709.         
  710.             newRow = LAddRow(1, 30000, gTheList);
  711.             SetPt(&theCell, 0, newRow);
  712.             LSetCell(&(**tempTrashItem).listEntry, sizeof(ListEntryRec), theCell, gTheList);
  713.  
  714.         HUnlock(tempTrashItem);
  715.  
  716.         tempTrashItem = (**tempTrashItem).next;
  717.     }
  718.     
  719. }
  720.  
  721. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  722.  
  723. long    GetTotalSelected(ListHandle gTheList)
  724. {
  725. Cell theCell;
  726. short    totalSize = 0;
  727.  
  728.     SetPt(&theCell, 0, 0);
  729.     while (LGetSelect(TRUE, &theCell, gTheList) == TRUE) 
  730.     {
  731.     ListEntryRec    listEntry;
  732.     short                dataLen;
  733.     
  734.         dataLen = sizeof(ListEntryRec);
  735.         LGetCell(&listEntry, &dataLen, theCell, gTheList);
  736.  
  737.         totalSize += listEntry.fileSize;
  738.         
  739.         LNextCell (  TRUE ,  TRUE , &theCell, gTheList ); 
  740.     }
  741.     
  742.     return(totalSize);
  743. }
  744.  
  745. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  746.  
  747. void    SelectAll(ListHandle gTheList)
  748. {
  749. Cell    theCell;
  750. short    count;
  751. char    listState;
  752.  
  753.     listState = HGetState(gTheList);
  754.     HLock(gTheList);
  755.     for (count = 0 ; count <= (**gTheList).dataBounds.bottom - 1 ; count++)
  756.     {
  757.         SetPt(&theCell, 0, count);
  758.         LSetSelect(TRUE, theCell, gTheList);
  759.     }
  760.     HSetState(gTheList, listState);
  761. }
  762.  
  763. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  764.  
  765. void    DeselectAll(ListHandle gTheList)
  766. {
  767. Cell    theCell;
  768. char    listState;
  769.  
  770.     listState = HGetState(gTheList);
  771.     HLock(gTheList);
  772.     SetPt(&theCell, 0, 0);
  773.     while (LGetSelect(TRUE, &theCell, gTheList) == TRUE) 
  774.     {    
  775.         LSetSelect(FALSE, theCell, gTheList);
  776.         LNextCell (TRUE, TRUE, &theCell, gTheList); 
  777.     }
  778.     HSetState(gTheList, listState);
  779. }
  780.  
  781. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  782.  
  783. pascal Boolean myLClikLoop(void)
  784. {
  785. Cell            theCell;
  786. char    listState;
  787.  
  788.     listState = HGetState(gTheList);
  789.     HLock(gTheList);
  790.  
  791.     SetPt(&theCell, 0, 0);
  792.     while (LGetSelect(TRUE, &theCell, gTheList) == TRUE) 
  793.     {
  794.     ListEntryRec    listEntry;
  795.     short            dataLen;
  796.     Cell            nextCell;
  797.     short            startingDepth;
  798.     short            currentDepth;
  799.     
  800.         dataLen = sizeof(ListEntryRec);
  801.         LGetCell(&listEntry, &dataLen, theCell, gTheList);
  802.  
  803.         if (listEntry.type <= 3 )
  804.         {
  805.             nextCell = theCell;
  806.             startingDepth = listEntry.depth;
  807.             currentDepth = startingDepth;
  808.         
  809.             do {
  810.             ListEntryRec    tempListEntry;
  811.             short            dataLen;
  812.             
  813.                 dataLen = sizeof(ListEntryRec);
  814.                 nextCell.v++;
  815.                 LGetCell(&tempListEntry, &dataLen, nextCell, gTheList);
  816.                 currentDepth = tempListEntry.depth;
  817.                 if (currentDepth > startingDepth)
  818.                 {
  819.                     LSetSelect(TRUE, nextCell, gTheList);
  820.                 }
  821.             
  822.             } while( (currentDepth > startingDepth) && (nextCell.v <= (**gTheList).dataBounds.bottom));
  823.         }
  824.         
  825.         LNextCell (  TRUE ,  TRUE , &theCell, gTheList ); 
  826.     }
  827.  
  828.     HSetState(gTheList, listState);        
  829.     return(TRUE);
  830. }
  831.  
  832. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  833.  
  834. void    DeleteSelected(ListHandle gTheList)
  835. {
  836. Cell        theCell;
  837. short        totalSize = 0;
  838. short        maxDepth = 0;
  839. short        totalToBeSelected = 0;
  840.  
  841.     SetPt(&theCell, 0, 0);
  842.     while (LGetSelect(TRUE, &theCell, gTheList) == TRUE) 
  843.     {
  844.     ListEntryRec    listEntry;
  845.     short            dataLen;
  846.     
  847.         dataLen = sizeof(ListEntryRec);
  848.         LGetCell(&listEntry, &dataLen, theCell, gTheList);
  849.         
  850.         if (listEntry.depth > maxDepth)
  851.         {
  852.             maxDepth = listEntry.depth;
  853.         }
  854.         
  855.         totalToBeSelected++;
  856.         
  857.         LNextCell (  TRUE ,  TRUE , &theCell, gTheList ); 
  858.     }
  859.     
  860.     if (maxDepth == 0)
  861.         return;
  862.     
  863.     do    { 
  864.         SetPt(&theCell, 0, 0);
  865.         while (LGetSelect(TRUE, &theCell, gTheList) == TRUE) 
  866.         {
  867.         ListEntryRec    listEntry;
  868.         short            dataLen;
  869.     
  870.             dataLen = sizeof(ListEntryRec);
  871.             LGetCell(&listEntry, &dataLen, theCell, gTheList);
  872.             
  873.             if (listEntry.depth == maxDepth)
  874.             {
  875.             OSErr         myErr;
  876.             HFileParam  pb;
  877.             StringPtr    theString;
  878.             
  879.                 pb.ioCompletion = nil;
  880.                 pb.ioVRefNum = listEntry.vRefNum;
  881.                 pb.ioDirID = listEntry.parID;
  882.                 theString = (StringPtr)NewPtrSysClear(256);
  883.                 BlockMove(&listEntry.name, theString, listEntry.name[0] + 1);
  884.                 pb.ioNamePtr = theString;
  885.             
  886.                 myErr = PBHDelete(&pb, FALSE);
  887.                 if (myErr != noErr)
  888.                 {
  889.                 Str255    errStr;
  890.                 
  891.                     LSetSelect(FALSE, theCell, gTheList);
  892.                 }
  893.                 else
  894.                 {
  895.                     LDelRow(1, theCell.v, gTheList);
  896.                     theCell.v--;
  897.  
  898.                     myErr = FlushVol(nil, listEntry.vRefNum);
  899.                 }
  900.                 
  901.                 DisposPtr(theString);
  902.             }
  903.             
  904.             LNextCell (FALSE, TRUE, &theCell, gTheList); 
  905.         }
  906.     }while (--maxDepth > 0);
  907.     
  908. }
  909.  
  910. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  911. //
  912. //    aBoolean = CheckForSystem7() - 
  913. //
  914. //    exit:    Boolean =     TRUE if we are running system 7 or up
  915. //                        FALSE if below system 7
  916. //
  917. //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  918.  
  919. Boolean CheckForSystem7(void)
  920. {
  921. short     myErr;
  922. long     currentSystem;
  923.  
  924.     myErr = Gestalt(gestaltSystemVersion, ¤tSystem);
  925.     if (myErr != noErr)
  926.     {
  927.         return(FALSE);
  928.     }
  929.     else
  930.     {
  931.         if (LoWord(currentSystem) < 0x0700)
  932.         {
  933.             return(FALSE);
  934.         }
  935.         else
  936.         {
  937.             return(TRUE);
  938.         }
  939.     }
  940. }
  941.  
  942. //{•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••}
  943.  
  944. Boolean KeyIsDown(unsigned  short  key)
  945. {
  946. unsigned char theKeyMap[16];
  947.  
  948.     GetKeys (&theKeyMap);
  949.     return ( (theKeyMap[key>>3] >> (key & 7)) & 1);
  950. }
  951.  
  952. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  953.  
  954. static Boolean myGNE (EventRecord *event,Boolean preResult) 
  955. {
  956. Boolean postResult = preResult;
  957.     
  958.     switch(event->what)
  959.        {
  960.         case nullEvent:
  961.             if (gOurMenuWasSelected == TRUE)
  962.             {
  963.                 DoTrashDialog();
  964.                 gOurMenuWasSelected = FALSE;
  965.             }
  966.             break;
  967.         default:
  968.             break;
  969.     }
  970.  
  971.     return(postResult);
  972. }
  973.  
  974. //•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
  975.  
  976. static void myJGNE (void) {
  977.   static Boolean inJGNE;
  978.   asm 
  979.   {
  980.     MOVE.L    A1,A0             ; save event record pointer from __GetA4
  981.     JSR       __GetA4           ; point A1 at our A4
  982.     MOVE.L    A4,-(A7)          ; save old A4
  983.     MOVE.L    (A1),A4           ; get new A4
  984.     MOVE.L    A0,A1             ; restore old A1
  985.     TST.B     inJGNE            ; is myJGNE busy?
  986.     BNE       @1                ; yes, so bail
  987.     MOVE.B    #true,inJGNE      ; mark myJGNE busy
  988.     MOVE.W    D0,-(A7)          ; push pre-result
  989.     MOVE.L    A1,-(A7)          ; push event record pointer
  990.     JSR       myGNE             ; do the real work
  991.     MOVE.L    (A7)+,A1          ; restore event record pointer
  992.     ADDQ.L    #2,A7             ; pop pre-result; post-result in D0
  993.     ASL.W     #8,D0             ; bump C boolean to Lisa
  994.     MOVE.W    D0,8(A7)          ; stash result where caller expects it
  995.     MOVE.B    #false,inJGNE     ; mark myJGNE not busy
  996. @1  MOVE.L    gOldJGNE,A0       ; get previous jGNE
  997.     MOVE.L    (A7)+,A4          ; restore A4
  998.     MOVE.L    A0,-(A7)          ; return to previous jGNE
  999.   }
  1000. }
  1001.  
  1002.  
  1003.